经典面试题之for 循环和闭包 | 您所在的位置:网站首页 › JavaScript For 循环 › 经典面试题之for 循环和闭包 |
前言
最近又温故而知新了一遍JavaScript的闭包,前面几年懵懵懂懂看了很多篇文章,今天再看还是受益匪浅,从而也搞懂了一道经典面试题,这个面试题之前也迟迟不理解,直到今天才豁然开朗。接下来就来逐步分析分析这道经典面试题。 题目 1: var data = []; 2: for (var i = 0; i < 3; i++) { 3: data[i] = function () { 4: console.log(i); 5: }; 6: } 7: 8: data[0](); // 3 9: data[1](); // 3 10:data[2](); // 3 分析:开始 JavaScript执行的是全局上下文作用域。 第一行声明的全局变量 data,并赋值为一个空数组 2-6行 定义了一个for 循环体,此时重点就在这个循环体里面了,再细细拆分来看。 循环体中 var i = 0; 声明的也是全局变量,i < 3; i++ 是循环条件。 循环体里面 变量data 开始进行被赋值,而且是经过了三次赋值,其结果拆开来写就是: data[0] = function(){ console.log(i) } data[1] = function(){ console.log(i) } data[2] = function(){ console.log(i) }此时注意 三次循环赋值 的结果的函数体内都是 console.log(i) ,而并不是console.log(0),console.log(1),console.log(2),此时的三个函数都是声明中,并未开始调用执行; 真正执行函数是 8 - 9 行,单独拿出每个数组中的函数执行。 再结合 全局声明的var i = 0; 经过三次循环,全局的 i 等于 3 了。 最后 调用函数体内的 console.log(i),此时的 i 找到的就是 全局变量 i = 3,最后输出执行的都是 console.log(3) 这个结果。 分析原因为什么会造成这样的结果。在没了解到闭包之前,还傻傻的以为输出的是 0,1,2,但因为词法作用域的原因,导致了这样的结果,因为污染了全局变量,导致函数作用域一层一层往上找的过程,没有找到对应点变量,就找了全局的变量。 解决方案相信网上也有很多这类面试题的解法,我也不过多描述,主要氛围异步setTimeOut处理,和ES6 let声明处理。 setTimeOut 自执行函数和闭包 var data = []; for (var i = 0; i < 3; i++) { (function(i){ setTimeout(data[i] = function () { console.log(i); }, 0) })(i) } data[0](); data[1](); data[2](); 用 let var data = []; for (let i = 0; i < 3; i++) { data[i] = function () { console.log(i); } } data[0](); data[1](); data[2](); 最后经过这次理解函数的闭包,再结合这道经典面试题,让我更深刻的理解了一遍闭包中的全局作用域 和 词法作用域。突然发现好多原理性的东西都是需要多看几遍才能深刻理解,每次看都有或多或少的收货。 |
CopyRight 2018-2019 实验室设备网 版权所有 |